home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks ’87 / Source ƒ.sit / Source ƒ / C ƒ / CITADEL BBS 'C' SRC / MISC.C < prev    next >
C/C++ Source or Header  |  1987-01-14  |  23KB  |  736 lines

  1. /************************************************************************/
  2. /*                misc.c                    */
  3. /*                                    */
  4. /*    Random functions.                        */
  5. /************************************************************************/
  6.  
  7. /************************************************************************/
  8. /*                history                 */
  9. /*                                    */
  10. /* 86Aug19 HAW    Kill history because of space problems.         */
  11. /* 84Jun10 JLS    Function changedate() installed.            */
  12. /* 84May01 HAW    Starting 1.50a upgrade.                 */
  13. /* 83Mar12 CrT    from msg.c                        */
  14. /* 83Mar03 CrT & SB   Various bug fixes...                */
  15. /* 83Feb27 CrT    Save private mail for sender as well as recipient.    */
  16. /* 83Feb23    Various.  transmitFile() won't drop first char on WC... */
  17. /* 82Dec06 CrT    2.00 release.                        */
  18. /* 82Nov05 CrT    Stream retrieval.  Handles messages longer than MAXTEXT.*/
  19. /* 82Nov04 CrT    Revised disk format implemented.            */
  20. /* 82Nov03 CrT    Individual history begun.  General cleanup.        */
  21. /************************************************************************/
  22.  
  23. #include "ctdl.h"
  24.  
  25. /************************************************************************/
  26. /*                contents                */
  27. /*                                    */
  28. /*    changeDate()        allow changing of date            */
  29. /*    configure()        sets terminal parameters via dialogue    */
  30. /*    crashout()        crashes out of Citadel in case of bug    */
  31. /*    diskSpaceLeft()     amount of space left on specified disk    */
  32. /*    doCR()            newline on modem and console        */
  33. /*    download()        menu-level routine for WC-protocol sends*/
  34. /*    getdate()        gets date from MSDOS system clock.    */
  35. /*    ingestFile()        puts file in held message buffer    */
  36. /*    patchDebug()        display/patch byte            */
  37. /*    printDate()        prints out date             */
  38. /*    putBufChar()        .EWM/.EXM/.EWN/.EXN internal        */
  39. /*    putFLChar()        readFile() -> disk file interface    */
  40. /*    setdate()        sets the date                */
  41. /*    transmitFile()        send a host file, no formatting     */
  42. /*    tutorial()        first level for printing a help file    */
  43. /*    upLoad()        menu-level read-via-WC-protocol fn    */
  44. /*    visible()        convert control chars to letters    */
  45. /*    writeTutorial()     prints a .hlp file            */
  46. /************************************************************************/
  47.  
  48. /************************************************************************/
  49. /*           External variable declarations in MISC.C        */
  50. /************************************************************************/
  51. static char    *monthTab[13] = {"", "Jan", "Feb", "Mar",
  52.                      "Apr", "May", "Jun",
  53.                      "Jul", "Aug", "Sep",
  54.                      "Oct", "Nov", "Dec" };
  55. FILE         *upfd;
  56. int         masterCount;
  57. int         acount;
  58. int         byteRate;    /* Bytes/sec that modem is set for.    */
  59.  
  60. char         *NoFileStr = "\n No %s.\n";
  61. char         *who_str = "who";
  62. char         *strFile = "filename";
  63. char         *VERSION = "2.12";
  64. char         *ALL_LOCALS = "&L";
  65. char         *R_SH_MARK  = "&&";
  66. char         *WRITE_LOCALS = "All Local Systems";
  67.  
  68. int fixVers = 128;
  69. int majorVers = 34;
  70. char *netVersion = "1.6";
  71.  
  72. #define AUDIT    9000
  73. char        audit[AUDIT];
  74.  
  75. /************************************************************************/
  76. /*           External variable definitions for MISC.C        */
  77. /************************************************************************/
  78. extern struct config    cfg;        /* Lots an lots of variables    */
  79. extern struct logBuffer logBuf;     /* Person buffer        */
  80. extern struct aRoom    roomBuf;    /* Room buffer            */
  81. extern struct rTable    roomTab[];
  82. extern struct msgB    msgBuf;
  83. extern struct msgB    tempMess;
  84. extern int        outPut;
  85. extern unsigned char    termNulls;    /* How many nulls?        */
  86. extern unsigned char    termWidth;    /* How many columns?        */
  87. extern char        termUpper;    /* Upper only?            */
  88. extern char        termLF;     /* Linefeeds?            */
  89. extern char        onConsole;
  90. extern char        expert;     /* expert?            */
  91. extern char        aide;        /* aide?            */
  92. extern char        sendTime;    /* Show time message created?    */
  93. extern unsigned char    crtColumn;    /* where are we on screen now?    */
  94. extern char        loggedIn;    /* Is we logged in?        */
  95. extern char        *indexTable;
  96. extern char        outFlag;    /* Output flag            */
  97. extern char        haveCarrier;    /* Do we still got carrier?    */
  98. extern char        heldMess;
  99. extern char        usingWCprotocol;/* WC flag            */
  100. extern char        prevChar;    /* previous char output     */
  101. extern char        textDownload;    /* flag             */
  102. extern char        whichIO;    /* Where I/O is         */
  103. extern char        echo;        /* Should we echo? echo? echo?    */
  104. extern FILE        *msgfl;
  105. extern FILE        *roomfl;
  106. extern FILE        *logfl;
  107. extern char        oldToo;
  108. extern int        exitValue;
  109.  
  110. /************************************************************************/
  111. /*           External function definitions for MISC.C        */
  112. /************************************************************************/
  113. char mAbort();
  114. long getNumber();
  115. FILE *safeopen();
  116.  
  117. /*
  118.  * This    function calculates the    CRC used by the    XMODEM/CRC Protocol
  119.  * The first argument is a pointer to the message block.
  120.  * The second argument is the number of    bytes in the message block.
  121.  * The function    returns    an integer which contains the CRC.
  122.  * The low order 16 bits are the coefficients of the CRC.
  123.  * Taken from XYMODEM.DOC -- HAW.
  124.  */
  125. int calcrc(ptr,    count)
  126. char *ptr;
  127. int count;
  128. {
  129.     int    crc, i;
  130.  
  131.     crc    = 0;
  132.     while (--count >= 0) {
  133.        crc = crc ^ (int)*ptr++ << 8;
  134.        for (i = 0; i < 8; ++i)
  135.            if (crc & 0x8000)
  136.            crc = crc <<    1 ^ 0x1021;
  137.            else
  138.            crc = crc <<    1;
  139.        }
  140.     return (crc    & 0xFFFF);
  141. }
  142.  
  143. /************************************************************************/
  144. /*    changedate() gets the date from the aide and remembers it    */
  145. /************************************************************************/
  146. changeDate()
  147. {
  148.     int year, day, hours, minutes;
  149.     char *month;
  150.  
  151.     getdate(&year, &month, &day, &hours, &minutes);
  152.     mPrintf("Current date is: %d%s%02d\n ", year, month, day);
  153.     mPrintf("Current time is: %d:%02d\n ", hours, minutes);
  154.     if (!getYesNo("Enter a new date & time"))
  155.     return ;
  156.     setdate();
  157. }
  158.  
  159. /************************************************************************/
  160. /*    configure() sets up terminal width etc via dialogue        */
  161. /************************************************************************/
  162. configure(showVals)
  163. char showVals;
  164. {
  165.     if (showVals && loggedIn) {
  166.     mPrintf("\n Your current setup:\n ");
  167.     mPrintf("%s, ", (expert) ? "Expert" : "Non-expert");
  168.  
  169.     mPrintf("%s,\n %slinefeeds, %d nulls,",
  170.         termUpper  ?  "UPPERCASE ONLY" : "Upper and Lower case",
  171.         termLF     ?  ""           : "no ",
  172.         termNulls
  173.     );
  174.     mPrintf(" screen width is %d\n ", termWidth);
  175.     mPrintf("%s time messages created,\n ",
  176.             sendTime ? "Print" : "Do not print");
  177.     mPrintf("%s last Old message on <N>ew Message request.",
  178.             oldToo ? "Print" : "Do not print");
  179.     mPrintf("\n ");
  180.     if (!getYesNo("Reset your configuration")) return;
  181.     }
  182.  
  183.     mPrintf("\n ");
  184.     termWidth    = (int) getNumber(" Screen width", 10l, 255l);
  185.     termNulls    = (int) getNumber(" #Nulls (normally 0)", 0l, 255l);
  186.     termUpper    =!getYesNo(" Do you have lower case"     ) ? TRUE : FALSE;
  187.     termLF    = getYesNo(" Do you need Linefeeds"     ) ? TRUE : FALSE;
  188.     expert    = getYesNo(" Are you an experienced Citadel user")
  189.                             ? TRUE : FALSE;
  190.     sendTime    = getYesNo(" Print time messages created") ? TRUE : FALSE;
  191.     if (expert)
  192.     oldToo = getYesNo(" Print last Old message on <N>ew Message request")
  193.                                       ? TRUE : FALSE;
  194.     else oldToo = FALSE;
  195.  
  196.     /* Now make it (only) semi-permanent     --JLS&HAW */
  197.     logBuf.lbwidth       = termWidth;
  198.     logBuf.lbnulls       = termNulls;
  199.     logBuf.lbflags.EXPERT  = expert;
  200.     logBuf.lbflags.UCMASK  = termUpper;
  201.     logBuf.lbflags.LFMASK  = termLF;
  202.     logBuf.lbflags.AIDE    = aide;
  203.     logBuf.lbflags.TIME    = sendTime;
  204.     logBuf.lbflags.OLDTOO  = oldToo;
  205. }
  206.  
  207. /************************************************************************/
  208. /*    crashout() Problems?  Out we go!!!                */
  209. /************************************************************************/
  210. crashout(message)
  211. char *message;
  212. {
  213.     extern char IBMinterrupts;
  214.     FILE *fd;        /* Record some crash data */
  215.     int  i;
  216.  
  217.     exitValue = CRASH_EXIT;
  218.     outFlag = IMPERVIOUS;
  219.    mPrintf("\n Whoops!! CRASHOLA!! Thanks and bye, leave mail on Test Sys!\n ");
  220.     printf("STATUS:\nmsgfl  %d\nlogfl  %d\nroomfl %d\n",
  221.             ferror(msgfl), ferror(logfl), ferror(roomfl));
  222.     interpret(cfg.pHangUp);
  223.     fclose(msgfl);
  224.     fclose(roomfl);
  225.     fclose(logfl);
  226.     fd = safeopen("crash", "w");
  227.     fprintf(fd, message);
  228.     fclose(fd);
  229.     fd = safeopen("audit", "w");
  230.     for (i = 0; i < AUDIT; i++) {
  231.     fputc(audit[i], fd);
  232.     if ((i+1) % 70 == 0) fprintf(fd, "\n");
  233.     }
  234.     fprintf(fd, "\n\ncounter = %d\n", acount);
  235.     fclose(fd);
  236.     writeSysTab();
  237.     modemClose();
  238.     exit(exitValue);
  239. }
  240.  
  241. /************************************************************************/
  242. /*    diskSpaceLeft() Amount of space left on specified disk        */
  243. /************************************************************************/
  244. diskSpaceLeft(drive, sectors, bytes)
  245. char drive;
  246. long *bytes;
  247. long *sectors;
  248. {
  249.     struct regval s;
  250.     long temp;
  251.  
  252.     s.ax = 0x3600;
  253.     s.dx = toUpper(drive) - 'A' + 1;
  254.     sysint21(&s, &s);
  255.     if (s.ax == 0xffff) return FALSE;
  256.     temp = s.ax;
  257.     *bytes = temp * s.bx * s.cx;
  258.     *sectors = ((*bytes) + 127) / SECTSIZE;
  259.     return TRUE;
  260. }
  261.  
  262. /************************************************************************/
  263. /*    doCR() does a newline on modem and console            */
  264. /************************************************************************/
  265. doCR()
  266. {
  267.     int i;
  268.  
  269.     crtColumn    = 1;
  270.     if (outFlag != OUTOK &&    /* output is being s(kip)ped    */
  271.     outFlag != IMPERVIOUS)
  272.     return;
  273.  
  274.     if (outPut == DISK) fprintf(upfd, "\n");
  275.     else {
  276.     if (usingWCprotocol == WC_NONE)
  277.         mputChar(NEWLINE);
  278.     if (haveCarrier) {
  279.         if (usingWCprotocol == WC_NONE) {
  280.         outMod('\r');
  281.         for (i = termNulls;  i;  i--) outMod(0);
  282.         if (termLF) outMod('\n');
  283.         } else {
  284.         sendWCChar('\r');
  285.         if (termLF) sendWCChar('\n');
  286.         }
  287.     }
  288.     }
  289.     prevChar    = ' ';
  290. }
  291.  
  292. /************************************************************************/
  293. /*    download() is the menu-level send-message-via-WC-protocol fn    */
  294. /************************************************************************/
  295. download(whichMess, revOrder, whatkind)
  296. char whichMess, revOrder, whatkind;
  297. {
  298.     outFlag    = OUTOK;
  299.     if (!expert)   tutorial("wcdown.blb");
  300.  
  301.     if (!getYesNo("Ready"))  return;
  302.  
  303.     /* here we go: */
  304.     echo        = NEITHER;
  305.     usingWCprotocol    = whatkind;    /* all points bulletin        */
  306.  
  307.     if (doWC(STARTUP)) {
  308.  
  309.     if (whichMess != GLOBALnEW)
  310.         showMessages(whichMess, revOrder);
  311.     else
  312.         doGlobal(revOrder);
  313.  
  314.     doWC(FINISH);
  315.  
  316.     }
  317.  
  318.     setUp(FALSE);
  319.     usingWCprotocol    = WC_NONE;
  320. }
  321.  
  322. /************************************************************************/
  323. /*    doGlobal() Does .R{W,X}G                    */
  324. /************************************************************************/
  325. doGlobal(revOrder)
  326. char revOrder;
  327. {
  328.     while (outFlag != OUTSKIP    &&   gotoRoom("", 'R'))   {
  329.     givePrompt();
  330.     mPrintf("read new\n ");
  331.     showMessages(NEWoNLY, revOrder);
  332.     }
  333. }
  334.  
  335. /************************************************************************/
  336. /*    formRoom() returns a string with the room formatted        */
  337. /************************************************************************/
  338. char *formRoom(roomNo, showPriv)
  339. int roomNo, showPriv;
  340. {
  341.     static char display[40];
  342.     int     one, two;
  343.     static char matrix[2][2] =
  344.       {  { '>', ')' } ,
  345.      { ']', ':' } } ;
  346.  
  347.     one = roomTab[roomNo].rtflags.MSDOSDIR;
  348.     two = roomTab[roomNo].rtflags.SHARED;
  349.     if (roomTab[roomNo].rtflags.INUSE) {
  350.     sPrintf(display, "%s%c%s",
  351.         roomTab[roomNo].rtname,
  352.         matrix[one][two],
  353.         (!roomTab[roomNo].rtflags.PUBLIC && showPriv) ? "*" : "");
  354.     }
  355.     else display[0] = '\0';
  356.     return display;
  357. }
  358.  
  359. /************************************************************************/
  360. /*    getdate() retrieves system date and returns in the parameters    */
  361. /************************************************************************/
  362. getdate(year, month, day, hours, minutes)
  363. int *year, *day, *hours, *minutes;
  364. char **month;
  365. {
  366. #ifdef MSDOS
  367.     struct regval s;
  368.  
  369.     s.ax = 0x2a00;
  370.     sysint21(&s, &s);
  371.     *year  = s.cx - 1900;
  372.     *month = monthTab[(s.dx & 0xff00) >> 8];
  373.     *day   = (s.dx & 0x00ff);
  374.     s.ax = 0x2c00;
  375.     sysint21(&s, &s);
  376.     *hours   = (s.cx & 0xff00) >> 8;
  377.     *minutes = s.cx & 0x00ff;
  378. #else
  379.     *year  = interpret(pGetYear);
  380.     *month = interpret(pGetMonth);
  381.     *day   = interpret(pGetDay);
  382.     *hours = *minutes = 0;
  383. #endif
  384. }
  385.  
  386. /************************************************************************/
  387. /*    ingestFile() Puts the given file in the held msg buffer     */
  388. /************************************************************************/
  389. ingestFile()
  390. {
  391.     char  filename[100];    /* Paths, etc.... */
  392.     FILE  *fd;
  393.     int   getc(), c, index;
  394.  
  395.     getNormStr(strFile, filename, 99, ECHO);
  396.     if ((fd = safeopen(filename, "r")) == NULL) {
  397.     mPrintf(NoFileStr, filename);
  398.     return;
  399.     }
  400.     index = (heldMess) ? strLen(tempMess.mbtext) : 0;
  401.     while ((c = getc(fd)) != EOF && index < MAXTEXT - 2) {
  402.     if (c) tempMess.mbtext[index++] = c;
  403.     }
  404.     tempMess.mbtext[index] = 0;
  405.     fclose(fd);
  406.     heldMess = TRUE;
  407. }
  408.  
  409. /************************************************************************/
  410. /*    printDate() prints out current date.                */
  411. /************************************************************************/
  412. printDate()
  413. {
  414.     int  day, year, h, m;
  415.     char *month;
  416.  
  417.     getdate(&year, &month, &day, &h, &m);
  418.     mPrintf("%d%s%02d ", year, month, day);
  419. }
  420.  
  421. /************************************************************************/
  422. /*    putBufChar() is used to upload messages via WC            */
  423. /*    returns: ERROR on problems else TRUE                */
  424. /************************************************************************/
  425. putBufChar(c)
  426. int  c;
  427. {
  428.     char result;
  429.     static char ourFilter[] =
  430.      /* 0 */    { 0,    0,   0,   0,     0,   0,   0,    0,   0,   ' ',
  431.      /* 10 */      '\n', 0,   0,   '\n',  0,   0,   0,    0,   0,   0,
  432.      /* 20 */      0,    0,   0,   0,     0,   0,   0,    0,   0,   0,
  433.      /* 30 */      0,    0,   ' ', '!',     '"', '#', '$', '%', '&', '\'',
  434.      /* 40 */      '(',    ')', '*', '+',     ',', '-', '.', '/', '0', '1',
  435.      /* 50 */      '2',    '3', '4', '5',     '6', '7', '8', '9', ':', ';',
  436.      /* 60 */      '<',    '=', '>', '?',     '@', 'A', 'B', 'C', 'D', 'E',
  437.      /* 70 */      'F',    'G', 'H', 'I',     'J', 'K', 'L', 'M', 'N', 'O',
  438.      /* 80 */      'P',    'Q', 'R', 'S',     'T', 'U', 'V', 'W', 'X', 'Y',
  439.      /* 90 */      'Z',    '[', '\\', ']',  '^', '_', '`', 'a', 'b', 'c',
  440.      /* 100 */      'd',    'e', 'f',  'g',  'h', 'i', 'j', 'k', 'l', 'm',
  441.      /* 110 */      'n',    'o', 'p',  'q',  'r', 's', 't', 'u', 'v', 'w',
  442.      /* 120 */      'x',    'y', 'z',  '{',  '!', '}', '~', 0  };
  443.  
  444.     if (masterCount > MAXTEXT - 2) return ERROR;
  445.  
  446.     c &= 0x7F;                    /* strip high bit    */
  447.     result = cfg.filter[c];
  448.     if (result == '\0') {
  449.     return TRUE;
  450.     }
  451.     msgBuf.mbtext[masterCount++] = result;
  452.     msgBuf.mbtext[masterCount]     = 0;    /* EOL just for luck    */
  453.     return TRUE;
  454. }
  455.  
  456. /************************************************************************/
  457. /*    putFLChar() is used to upload files                */
  458. /*    returns: ERROR on problems else TRUE                */
  459. /************************************************************************/
  460. putFLChar(c)
  461. char c;
  462. {
  463.     if (fputc(c, upfd) != EOF) return TRUE;
  464.     /* else */               printf("Write error: %d\n", ferror(upfd));
  465.                    return ERROR;
  466. }
  467.  
  468. /************************************************************************/
  469. /*    setdate() Sets the date.                    */
  470. /************************************************************************/
  471. setdate()
  472. {
  473. #ifdef MSDOS
  474.     struct regval s;
  475.  
  476.     while (1) {
  477.     s.cx  = (int) getNumber("Year",  85l, 99l) + 1900;
  478.     s.dx  = (int) getNumber("Month", 1l,  12l) << 8  ;
  479.     s.dx += (int) getNumber("Day",     1l,  31l)     ;
  480.     s.ax = 0x2b00;
  481.     sysint21(&s, &s);
  482.     if (s.ax & 0xff)
  483.         mPrintf("Invalid date\n ");
  484.     else
  485.         break;
  486.     }
  487.     while (1) {
  488.     s.cx  = (int) getNumber("Hour",   0l, 23l) << 8;
  489.     s.cx += (int) getNumber("Minute", 0l, 59l)     ;
  490.     s.dx  = 0;
  491.     s.ax = 0x2d00;
  492.     sysint21(&s, &s);
  493.     if (s.ax & 0xff)
  494.         mPrintf("Invalid time\n ");
  495.     else
  496.         break;
  497.     }
  498. #else
  499.     interpret(pInitDate);
  500. #endif
  501. }
  502.  
  503. /************************************************************************/
  504. /*    systemCommands() Some MS-DOS commands                */
  505. /************************************************************************/
  506. systemCommands()
  507. {
  508.     int  errorCode;
  509.     char filename[200];
  510.  
  511.     while (onLine()) {
  512.     outFlag = OUTOK;
  513.     mPrintf("\n System commands: ");
  514.  
  515.     switch (toUpper(iChar())) {
  516.     case 'X':
  517.         mPrintf("\bExit from System Commands menu\n ");
  518.         return ;
  519.     case 'D':
  520.         mPrintf("elete file\n ");
  521.         getNormStr(strFile, filename, 199, ECHO);
  522.         doCR();
  523.         mPrintf("File %s.\n ", (unlink(filename) == 0) ?
  524.                 "deleted" : "not found");
  525.         break;
  526.     case 'O':
  527.         mPrintf("utside commands\n One moment, please.");
  528.         writeSysTab();
  529.         getString("command line", filename, 198, FALSE, ECHO);
  530.         if ((errorCode = system(filename)) != 0) {
  531.         mPrintf("FAILED: ");
  532.         switch (errorCode) {    /* See the C-86 manual for this */
  533.             case 1: mPrintf("VeryBadUnknownError\n ");        break;
  534.             case 2: mPrintf("Command.com not found\n ");    break;
  535.             case 5: mPrintf("Access denied\n ");        break;
  536.             case 8: mPrintf("Insufficient memory\n ");        break;
  537.             case 10: mPrintf("Bad environment\n ");        break;
  538.             default: mPrintf("Bad return Value\n ");        break;
  539.         }
  540.         }
  541.         unlink(indexTable);
  542.         break;
  543.     case '?':
  544.         tutorial("sysopt.mnu");
  545.         break;
  546.     default:
  547.         if (!expert)    mPrintf(" ?(Type '?' for menu)\n "        );
  548.         else        mPrintf(" ?\n "                );
  549.         break;
  550.     }
  551.     }
  552. }
  553.  
  554. /************************************************************************/
  555. /*    transmitFile() dumps a host file with no formatting        */
  556. /************************************************************************/
  557. transmitFile(filename)
  558. char *filename;
  559. {
  560. #define CPMEOF    26            /* For CP/M files, EOF == ^Z    */
  561.     int  getc(), sendWCChar();
  562.     long fseek(), totalSectors, fileSize;
  563.     long Secs, Mins, totalTime, totalBytes;
  564.     char protocol;
  565.     FILE *fbuf;
  566.     int  c;
  567.  
  568.     outFlag    = OUTOK;
  569.  
  570.     if ((fbuf = safeopen(filename, "rb")) == NULL) {
  571.     usingWCprotocol = WC_NONE;
  572.     mPrintf(NoFileStr, filename);
  573.     return(ERROR);
  574.     }
  575.  
  576.     doCR();
  577.     if (usingWCprotocol != WC_NONE)   {
  578.     protocol = usingWCprotocol;
  579.     usingWCprotocol = FALSE;
  580.     if (byteRate != 0) {
  581.         fileSize = fseek(fbuf, -1l, 2) + 1;
  582.         rewind(fbuf);
  583.         totalSectors = ((fileSize + SECTSIZE - 1) / SECTSIZE);
  584. #ifdef OLDCALCS
  585.         if (byteRate == 30)
  586.         totalTime    = (totalSectors * 9) / 2;
  587.         else if (byteRate == 120)
  588.         totalTime    = (totalSectors * 3) / 2;
  589.         else if (byteRate == 240)         /* Best guess  */
  590.         totalTime    = (totalSectors * 3) / 4;
  591. #else
  592.         if (byteRate == 30)
  593.         totalTime    = (totalSectors * 10);
  594.         else if (byteRate == 120)
  595.         totalTime    = (totalSectors * 5) / 4;
  596.         else if (byteRate == 240)         /* Best guess  */
  597.         totalTime    = (totalSectors * 5) / 8;
  598. #endif
  599.         Mins     = totalTime / 60;
  600.         Secs     = totalTime % 60;
  601.         mPrintf("\n Total time to download '%s' should be about ",filename);
  602.         if (Mins != 0l)
  603.         mPrintf("%ld minute%s, ", Mins,
  604.                 (Mins == 1l) ? "" : "s");
  605.  
  606.         mPrintf("%2ld second%s (%ld blocks).",
  607. Secs, (Secs == 1l) ? "" : "s", totalSectors);
  608.     }
  609.  
  610.     if (!getYesNo("Ready for WC transfer")) {
  611.         fclose(fbuf);
  612.         return ERROR;
  613.     }
  614.     usingWCprotocol = protocol;
  615.     sendWCFile(fbuf);
  616.     usingWCprotocol = WC_NONE;
  617.     oChar(BELL);
  618.     return ;
  619.     }
  620.  
  621.     while ((c = getc(fbuf)) != ERROR && (c != CPMEOF || !textDownload))  {
  622.     mputChar(c);
  623.     if (interpret(cfg.pCarrDetect)) outMod(c);
  624.     if (mAbort() || (whichIO == MODEM && !gotCarrier())) break;
  625.     }
  626.  
  627.     fclose(fbuf);
  628. }
  629.  
  630. /************************************************************************/
  631. /*    tutorial() prints file <filename> on the modem & console    */
  632. /*    Returns:    TRUE on success else ERROR            */
  633. /************************************************************************/
  634. #define MAXWORD 256
  635. tutorial(filename)
  636. char *filename;
  637. {
  638.     FILE *fbuf;
  639.     char line[MAXWORD];
  640.     int  toReturn;
  641.  
  642.     toReturn    = TRUE;
  643.  
  644.     outFlag    = OUTOK;
  645.     if (filename[1] == ':' || (fbuf = safeopen(filename, "r")) == NULL) {
  646.     mPrintf(NoFileStr, filename);
  647.     toReturn    = ERROR;
  648.     } else {
  649.     writeTutorial(fbuf, TRUE);
  650.     fclose(fbuf);
  651.     }
  652.  
  653.     return   toReturn;
  654. }
  655.  
  656. /************************************************************************/
  657. /*    upLoad() enters a file into current directory            */
  658. /************************************************************************/
  659. upLoad()
  660. {
  661.     char fileName[NAMESIZE], *s;
  662.     int  putFLChar();
  663.     char successful;
  664.  
  665.     getNormStr(strFile, fileName, NAMESIZE, ECHO);
  666.  
  667.     if (fileName[1] != ':')   s = &fileName[0];
  668.     else              s = &fileName[2];
  669.  
  670.     if (!setSpace(roomBuf.rbdisk, roomBuf.rbdirname)) {
  671.     crashout("ERROR: DIRECTORY NOT FOUND!");
  672.     }
  673.  
  674.     if ((upfd = safeopen(s, "r")) != NULL) {
  675.     mPrintf("\n A %s already exists.\n", s);
  676.     fclose(upfd);
  677.     } else {
  678.     if (!expert) {
  679.         if (strLen(roomBuf.rbdirname) != 0) setSpace(roomBuf.rbdisk, "..");
  680.         setSpace(cfg.homeDisk, "");
  681.         tutorial("wcupload.blb");
  682.         setSpace(roomBuf.rbdisk, roomBuf.rbdirname);
  683.     }
  684.     if ((upfd = safeopen(s, "wb")) == NULL) {
  685.         mPrintf("\n Can't create %s!\n", s);
  686.     } else {
  687.         if (!getYesNo("Ready for WC transfer"))
  688.         successful = FALSE;
  689.         else
  690.         successful = readFile(putFLChar);
  691.         fclose(upfd);
  692.         if (!successful) unlink(s);
  693.         else {
  694.         sPrintf(msgBuf.mbtext, "File \"%s\" uploaded into %s by %s.",
  695.               s, roomBuf.rbname, logBuf.lbname);
  696.         aideMessage(FALSE);
  697.         putMessage(FALSE);    /* Now save message in this room*/
  698.         noteMessage(NULL, ERROR);
  699.         noteRoom();
  700.         }
  701.     }
  702.     }
  703.     if (strLen(roomBuf.rbdirname) != 0) setSpace(roomBuf.rbdisk, "..");
  704.     setSpace(cfg.homeDisk, "");
  705. }
  706.  
  707. /************************************************************************/
  708. /*    visible() converts given char to printable form if nonprinting    */
  709. /************************************************************************/
  710. char visible(c)
  711. unsigned char c;
  712. {
  713.     if (c==0xFF)  c = '$'    ;   /* start-of-message in message.buf    */
  714.     c            = c & 0x7F    ;   /* kill high bit otherwise        */
  715.     if ( c < ' ') c = c + 'A' -1;   /* make all control chars letters    */
  716.     if (c== 0x7F) c = '~'    ;   /* catch DELETE too         */
  717.     return(c);
  718. }
  719.  
  720. /************************************************************************/
  721. /*    writeTutorial() given a file, prints it             */
  722. /************************************************************************/
  723. writeTutorial(fd, noviceWarning)
  724. FILE *fd;
  725. char noviceWarning;
  726. {
  727.     char line[MAXWORD];
  728.  
  729.     rewind(fd);
  730.  
  731.     outFlag    = OUTOK;
  732.     if (!expert && noviceWarning) mPrintf("\n <J>ump <P>ause <S>top\n");
  733.     mPrintf(" \n");
  734.     while (fgets(line, MAXWORD, fd))   mPrintf("%s", line);
  735. }
  736.